﻿using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections.Generic;
using System.Timers;
using Message;
using System.Threading;

namespace LoginServer.Net
{
    public class ServNet
    {
        /// <summary>
        /// 实例
        /// </summary>
        public static ServNet instance;
        /// <summary>
        /// 心跳定时器
        /// </summary>
        System.Timers.Timer hbTimer = new System.Timers.Timer(1000);
        /// <summary>
        /// 心跳时间
        /// </summary>
        public long heartBeatTime = 8;
        /// <summary>
        /// 位置分发定时器
        /// </summary>
        System.Timers.Timer moveTimer = new System.Timers.Timer(200);

        /// <summary>
        /// 消息分发
        /// </summary>
        public MsgDisPatcher msgDist;
        /// <summary>
        /// 所有在线用户
        /// </summary>
        public Dictionary<int, PlayerSession> Users = new Dictionary<int, PlayerSession>();

        public ServNet()
        {
            instance = this;
            msgDist = new MsgDisPatcher();
        }

        public GameServer gameServer;

        public void Start(int port)
        {
            hbTimer.Elapsed += new ElapsedEventHandler(HandleHBTimer);
            hbTimer.AutoReset = false;
            hbTimer.Enabled = true;

            moveTimer.Elapsed += new ElapsedEventHandler(HandleMoveTimer);
            moveTimer.AutoReset = false;
            moveTimer.Enabled = true;

            gameServer = new GameServer();
            var serverConfig = new ServerConfig
            {
                Port = 6650, //set the listening port
                Ip = "Any",
                Name = "GameServer",
                //Other configuration options
                Mode = SocketMode.Tcp,
                MaxConnectionNumber = 2000,
                IdleSessionTimeOut = 600,
                TextEncoding = "UTF-8",
                SyncSend = true,
                SendBufferSize = 1024,
                ReceiveBufferSize = 1024,
                LogBasicSessionActivity = true,
                LogAllSocketException = true,
                KeepAliveTime = 300,
            };

            if (gameServer.Setup(serverConfig) == false)
            {
                Console.WriteLine("IpAndEnpoint Set Failed");
                return;
            }
            gameServer.NewSessionConnected += NewSessionConnected;
            gameServer.NewRequestReceived += NewRequestReceived;
            gameServer.SessionClosed += SessionClosed;

            if (gameServer.Start() == false)
            {
                Console.WriteLine("[服务器]启动失败");
                return;
            }

            //Thread t = new Thread(new ThreadStart(Update));
            //t.IsBackground = true;
            //t.Start();

            Console.WriteLine("[服务器]启动成功");
        }

        //public void Update()
        //{ //消息
        //    while (true)
        //    {
        //        msgDist.Update();
        //    }
        //}

        /// <summary>
        /// 新的玩家连接
        /// </summary>
        /// <param name="session"></param>
        private void NewSessionConnected(PlayerSession session)
        {
            Console.WriteLine("连接：" + session.RemoteEndPoint.ToString());
            session.isUse = true;
            msgDist.Update();
        }

        /// <summary>
        /// 收到玩家发送消息
        /// </summary>
        /// <param name="session"></param>
        /// <param name="requestInfo"></param>
        private void NewRequestReceived(PlayerSession session, BinaryRequestInfo requestInfo)
        {
            session.Receive(requestInfo.Key, requestInfo.Body);
            msgDist.Update();
        }
        /// <summary>
        /// 关闭时
        /// </summary>
        /// <param name="session"></param>
        /// <param name="value"></param>
        private void SessionClosed(PlayerSession session, CloseReason value)
        {
            Console.WriteLine("断开：" + session.RemoteEndPoint.ToString());
            session.Close();
            msgDist.Update();
        }

        /// <summary>
        /// 心跳
        /// </summary>
        public void HeartBeat()
        {
            long timeNow = Sys.GetTimeStamp();
            if (Users.Count > 0)
            {
                foreach (PlayerSession session in Users.Values)
                {
                    if (session != null && session.isUse && session.SocketSession.Client != null)
                    {
                        if (session.lastTickTime < timeNow - heartBeatTime)
                        {
                            Console.WriteLine("[心跳引起断开连接]:" + session.LocalEndPoint.ToString());
                            session.Close();
                        }
                    }
                }
            }
        }

        public void HandleHBTimer(object sender, ElapsedEventArgs e)
        {
            HeartBeat();
            hbTimer.Start();
        }

        public void HandleMoveTimer(object sender, ElapsedEventArgs e)
        {
            BroadCastMove();
            moveTimer.Start();
        }

        void BroadCastMove()
        {
            if (Users.Count > 0)
            {
                SToCMoves stcms = new SToCMoves();
                //Console.WriteLine(Users.Values.Count);
                foreach (PlayerSession session in Users.Values)
                {
                    if (session != null && session.isUse && session.SocketSession.Client != null)
                    {
                        CToSMove ctsmm = new CToSMove();
                        ctsmm.uid = session.uid;
                        ctsmm.uname = session.uname;
                        ctsmm.x = session.x;
                        ctsmm.y = session.y;
                        ctsmm.z = session.z;
                        ctsmm.angle = session.angle;
                        stcms.moves.Add(ctsmm);
                    }
                }
                foreach (PlayerSession session in Users.Values)
                {
                    if (session != null && session.isUse && session.SocketSession.Client != null)
                    {
                        session.SendObj(stcms);
                    }
                }
            }
        }
    }
}
